package com.example.nettydemo.utils;
import com.example.nettydemo.aspect.FieldConfig;
import com.example.nettydemo.pojo.bo.VGroup;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Author: wujing
 * Date:   2025/5/14 0:06
 * Description:
 * 1. 定义一个注解 @FieldConfig，用于标记字段的长度和类型。
 * 2. 在需要转换的类中，使用 @FieldConfig 注解标记每个字段。
 * 3. 编写一个工具类，用于将对象转换为格式化的字符串。
 * 4. 在工具类中，使用反射获取对象的字段，并根据 @FieldConfig 注解中的信息进行格式化。
 * 5. 编写一个工具类，用于将格式化的字符串解析回对象。
 * 6. 在工具类中，使用反射设置对象的字段值。
 * 7. 编写测试代码，验证工具类的功能。
 * 8. 注意处理日期格式的转换。
 * 9. 注意处理字符串的长度限制。
 * 10. 注意处理字符串的空格填充。
 * 11. 注意处理字符串的换行符。
 * 12. 注意处理字符串的特殊字符。
 * 13. 注意处理字符串的编码。
 * 14. 注意处理字符串的解码。
 * 15. 注意处理字符串的比较。
 * 16. 注意处理字符串的排序。
 * 17. 注意处理字符串的截取。
 * 18. 注意处理字符串的拼接。
 */
public class BeanToFormattedString {

    private final static DateTimeFormatter yyyyMMddHHmmssFormat = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

    private final static DateTimeFormatter yyyyMMddFormat = DateTimeFormatter.ofPattern("yyyyMMdd");

    /**
     * 将bean转换为格式化的字符串
     * @param bean
     * @return
     * @throws IllegalAccessException
     */
    public static String convertBeanToString(Object bean) throws IllegalAccessException {
        StringBuilder result = new StringBuilder();
        Class<?> clazz = bean.getClass();
        Field[] fields = clazz.getDeclaredFields();

        // 按照注解中的 order 属性排序
        Field[] sortedFields = Arrays.stream(fields)
                .filter(field -> field.isAnnotationPresent(FieldConfig.class))
                .sorted(Comparator.comparingInt(f -> f.getAnnotation(FieldConfig.class).order()))
                .toArray(Field[]::new);

        for (Field field : sortedFields) {
            FieldConfig fieldConfig = field.getAnnotation(FieldConfig.class);
            field.setAccessible(true); // 使得私有字段可访问
            Object value = field.get(bean);
            String processedValue;
            if(value instanceof List<?> valueList){
                if(!valueList.isEmpty()){
                    processedValue = valueList.stream().map(Object::toString).map(vv -> {
                        if (fieldConfig.type() == String.class) {
                            return processString(vv, fieldConfig.length());
                        } else if (fieldConfig.type() == Integer.class) {
                            return processInteger(vv, fieldConfig.length());
                        } else if (fieldConfig.type() == Timestamp.class) {
                            return processDateTime(vv);
                        } else if (fieldConfig.type() == Date.class) {
                            return processDate(vv);
                        } else {
                            return vv; // 默认处理
                        }
                    }).collect(Collectors.joining());
                    result.append(processedValue);
                }
            }else{
                if (fieldConfig.type() == String.class) {
                    processedValue = processString(value.toString(), fieldConfig.length());
                } else if (fieldConfig.type() == Integer.class) {
                    processedValue = processInteger(value.toString(), fieldConfig.length());
                } else if (fieldConfig.type() == Timestamp.class) {
                    processedValue = processDateTime(value);
                } else if (fieldConfig.type() == Date.class) {
                    processedValue = processDate(value);
                }else {
                    processedValue = value.toString(); // 默认处理
                }
                result.append(processedValue);
            }
        }
        return result.toString();
    }

    /**
     * 将格式化的字符串解析回bean
     * @param input
     * @param bean
     * @throws IllegalAccessException
     * @throws ParseException
     */
    public static void parseStringToBean(String input, Object bean) throws IllegalAccessException, ParseException {
        Class<?> clazz = bean.getClass();
        Field[] fields = clazz.getDeclaredFields();

        // 按照注解中的 order 属性排序
        Field[] sortedFields = Arrays.stream(fields)
                .filter(field -> field.isAnnotationPresent(FieldConfig.class))
                .sorted(Comparator.comparingInt(f -> f.getAnnotation(FieldConfig.class).order()))
                .toArray(Field[]::new);

        int currentIndex = 0;

        Object prevField = null;
        for (Field field : sortedFields) {
            FieldConfig fieldConfig = field.getAnnotation(FieldConfig.class);
            field.setAccessible(true); // 使得私有字段可访问

            int length = fieldConfig.length();
            boolean beList = fieldConfig.beList();
            int totalLength = length;
            if(beList){
                if(prevField instanceof Integer prevLength){
                    totalLength = prevLength * length;
                }
            }
            String substring = input.substring(currentIndex, currentIndex + totalLength);
            currentIndex += totalLength;

            if (fieldConfig.type() == String.class) {
                // 去掉右侧的空格，但最后一个字符不能是空格
                String value = substring.replaceAll("\\s+$", "");
                if (value.isEmpty()) {
                    value = substring; // 如果全是空格，保留原样
                }
                field.set(bean, value);
            } else if (fieldConfig.type() == Integer.class) {
                Integer value = Integer.parseInt(substring.trim());
                field.set(bean, value);
            } else if (fieldConfig.type() == Timestamp.class) {
                field.set(bean, Timestamp.valueOf(LocalDateTime.parse(substring.trim(),yyyyMMddHHmmssFormat)));
            } else if (fieldConfig.type() == Date.class) {
                field.set(bean, Date.from(LocalDate.parse(substring.trim(),yyyyMMddFormat).atStartOfDay(ZoneId.systemDefault()).toInstant()));
            } else if (fieldConfig.type() == VGroup.class) {
                field.set(bean, substring);
            } else {
                field.set(bean, substring); // 默认处理
            }
            prevField = field.get(bean);
        }
    }

    /**
     * 处理字符串
     * @param value
     * @param length
     * @return
     */
    private static String processString(String value, int length) {
        if (value == null) value = "";
        int requiredPadding = length - value.length();
        if (requiredPadding > 0) {
            if (requiredPadding == 1) {
                return value + " ";
            } else {
                return value + " ".repeat(requiredPadding);
            }
        } else {
            return value.substring(0, length);
        }
    }

    private static String processInteger(String value, int length) {
        return String.format("%0" + length + "d", Integer.parseInt(value));
    }

    private static String processDateTime(Object value) {
        if (value instanceof Timestamp date) {
            return yyyyMMddHHmmssFormat.format(date.toLocalDateTime());
        }
        return value.toString();
    }

    private static String processDate(Object value) {
        if (value instanceof Date date) {
            return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate().format(yyyyMMddFormat);
        }
        return value.toString();
    }

    private static String processBinary(Object value) {
        return value.toString();
    }

    public static String strChangeToGB18030(String str) throws UnsupportedEncodingException {
        return new String(str.getBytes("GB18030"), "GB18030");
    }
}